// Domien Nowicki
#include "QtSprite.h"
#include "QtRotateToEffect.h"
#include "QtMoveToEffect.h"
#include "QtScaleToEffect.h"
#include <QGraphicsScene>

QtSprite::QtSprite(QtSprite* parent): QGraphicsItem(parent), alpha(1), angle(0), scale(1,1)
{
	setZValue(0);
	QObject::connect(&effects, SIGNAL(Finished(QtAnimationEffect*)), this, SLOT(EmitFinished()));
	QObject::connect(&effects, SIGNAL(Started(QtAnimationEffect*)), this, SLOT(EmitStarted()));
}

QtSprite::~QtSprite()
{
}

void QtSprite::EmitFinished()
{
	emit Finished();
}

void QtSprite::EmitStarted()
{
	emit Started();
}

void QtSprite::Center()
{
	SetCenterPoint(QPointF( (int)boundingRect().width()/2, (int)boundingRect().height()/2 ));
}

const QPointF& QtSprite::CenterPoint() const
{
	return centerPoint;
}

void QtSprite::SetCenterPoint(const QPointF& point)
{
	centerPoint = point;

	translationMatrix.reset();
	translationMatrix.translate(-centerPoint.x(), -centerPoint.y());

	SetTransform();
}

void QtSprite::SetTransform()
{
	//setTransform( scaleMatrix * rotationMatrix * translationMatrix );
	setTransform( translationMatrix * scaleMatrix * rotationMatrix);
}

void QtSprite::SetAlpha(qreal newAlpha)
{
	if (alpha != newAlpha)
	{
		alpha = newAlpha;
		AlphaUpdated(alpha);
		update();
	}
}

qreal QtSprite::Alpha() const
{
	return alpha;
}

void QtSprite::SetAngle(qreal newAngle)
{
	angle = newAngle;

	rotationMatrix.reset();
	rotationMatrix.rotate(newAngle);

	SetTransform();
}

qreal QtSprite::Angle() const
{
	return angle;
}

void QtSprite::SetPosition(const QPointF& newPosition)
{
	setPos(newPosition);

	PositionUpdated(newPosition);
}

QPointF QtSprite::Position() const
{
	return pos();
}

void QtSprite::SetScale(unsigned int width, unsigned int height)
{
	qreal scalex = (qreal)width / boundingRect().width();
	qreal scaley = (qreal)height / boundingRect().height();

	scaleMatrix.reset();
	scaleMatrix.scale(scalex, scaley);

	scale.setX(scalex);
	scale.setY(scaley);
	SetTransform();
}

unsigned int QtSprite::ScaleWidth() const
{
	return scale.x() * boundingRect().width();
}

unsigned int QtSprite::ScaleHeight() const
{
	return scale.y() * boundingRect().height();
}

unsigned int QtSprite::Width() const
{
	return boundingRect().width();
}

unsigned int QtSprite::Height() const
{
	return boundingRect().height();
}

void QtSprite::MoveTo(const QPointF& endPosition, unsigned int duration)
{
	QtMoveToEffect effect;

	effect.SetDuration(duration);
	effect.SetEndPosition(endPosition);
	effect.SetTarget(this);

	AddEffect(&effect);
}

void QtSprite::RotateRightTo(qreal endAngle, unsigned int duration)
{
	QtRotateToEffect effect;

	effect.SetDuration(duration);

	if (endAngle < angle)
		effect.SetEndAngle(endAngle + 360);
	else
		effect.SetEndAngle(endAngle);
	effect.SetTarget(this);

	AddEffect(&effect);
}

void QtSprite::RotateLeftTo(qreal endAngle, unsigned int duration)
{
	QtRotateToEffect effect;

	effect.SetDuration(duration);
	if (endAngle > angle)
		effect.SetEndAngle(endAngle - 360);
	else
		effect.SetEndAngle(angle);
	effect.SetTarget(this);

	AddEffect(&effect);
}

void QtSprite::ScaleTo(unsigned int width, unsigned int height, unsigned int duration)
{
	QtScaleToEffect effect;

	effect.SetDuration(duration);
	effect.SetTarget(this);
	effect.SetEndScale(width, height);

	AddEffect(&effect);
}

void QtSprite::AddEffect(QtAnimationEffect *effect)
{
	effects.AddEffect(effect);
}

void QtSprite::AlphaUpdated(qreal alpha)
{
}

void QtSprite::Start()
{
	effects.Start();
}


void QtSprite::AddSprite(QtSprite* sprite)
{
	children.push_back(sprite);

	if (scene() != 0)
	{
		scene()->addItem(sprite);
	}
}

void QtSprite::AddToScene(QGraphicsScene *scene)
{
	std::list<QtSprite *>::iterator it;

	if (this->scene() != scene)
	{
		scene->addItem(this);
	}

	for(it = children.begin(); it!=children.end(); ++it)
	{
		QtSprite *sprite = *it;

		if (sprite->scene() == 0)
		{
			sprite->AddToScene(scene);
		}
	}
}

void QtSprite::PositionUpdated(const QPointF& position)
{
	std::list<QtSprite*>::iterator it;


	for(it = children.begin(); it!=children.end(); ++it)
	{
		(*it)->SetPosition(position);
	}
}

void QtSprite::SetDepth(qreal z)
{
	setZValue(z);
}

qreal QtSprite::Depth() const
{
	return zValue();
}

void QtSprite::Hide()
{
	hide();
}

void QtSprite::Show()
{
	show();
}

QPointF QtSprite::MapToScene(const QPointF& point) const
{
	return mapToScene(point);
}

QPointF QtSprite::MapFromScene(const QPointF& point) const
{
	return mapFromScene(point);
}

